import React, { PureComponent, ReactNode, CSSProperties } from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import cssAnimate, { isCssAnimationSupported } from 'css-animation';
import cx from 'classnames';
import omit from 'object.omit';

interface CSSAnimateProps {
  type?: string;
  callback?: () => void;
  duration?: number;
  delay?: number;
  component?: string;
  className?: string;
  children?: ReactNode;
  style?: CSSProperties;
}


class CSSAnimate extends PureComponent<CSSAnimateProps> {
  static defaultProps = {
    component: 'div'
  };

  static propTypes = {
    type: PropTypes.string,
    callback: PropTypes.func,
    duration: PropTypes.number,
    delay: PropTypes.number,
    component: PropTypes.string
  };

  componentDidMount(): void {
    const { type, callback } = this.props;
    this.animate(type, callback);
  }

  componentDidUpdate(prevProps: CSSAnimateProps): void {
    const { type, callback } = this.props;
    if (type !== prevProps.type) {
      this.animate(type, callback);
    }
  }

  animate = (type?: string, callback?: () => void): void => {
    const node = ReactDOM.findDOMNode(this);

    if (isCssAnimationSupported && type) {
      cssAnimate(node, type, callback);
    } else if (!isCssAnimationSupported) {
      console.warn('不支持css动画');
    }
  };

  render(): JSX.Element {
    const {
      className,
      children,
      delay,
      duration,
      style,
      component,
      ...otherProps
    } = this.props;

    const Component = component as keyof JSX.IntrinsicElements;
    
    const classnames = cx('animated', className);
    
    const _style: CSSProperties = { ...style };
    
    if (duration) {
      _style.animationDuration = `${duration}ms`;
      _style.WebkitAnimationDuration = `${duration}ms`;
    }

    if (delay) {
      _style.animationDelay = `${delay}ms`;
      _style.WebkitAnimationDelay = `${delay}ms`;
    }

    const divProps = omit(otherProps, [
      'type',
      'callback',
      'delay',
      'duration'
    ]);

    return (
      <Component className={classnames} {...divProps} style={_style}>
        {children}
      </Component>
    );
  }
}

export default CSSAnimate;